package org.ns.socket.client.handler;

import org.ns.socket.client.ByteBuffer;
import org.ns.socket.client.SocketContext;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Iterator;
import java.util.LinkedList;

public class BioSocketHandler extends AbstractSocketHandler {

    public BioSocketHandler() {

    }

    private Socket socket;

    private Thread thread;

    public void connect(String host, int port)throws IOException {
        if (socket == null) {
            socket = new Socket(host, port);
            socket.setSoTimeout(getSocketConfig().getSocketTimeout());
            thread = new Thread(this::run);
            thread.setDaemon(true);
            thread.start();
        } else {

        }
    }


    @Override
    public void write(Object msg) {
        synchronized (socket) {

            try {
                OutputStream out = socket.getOutputStream();
                if (socket.isOutputShutdown()) {
                    return;
                }

                byte[] buf = writeHandler(msg);
                if (buf != null && buf.length > 0) {
                    out.write(buf);
                    out.flush();
                }
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    private void run() {
        ByteBuffer byteBuffer = new ByteBuffer(10240);
        byte[] cache = new byte[1024];
        LinkedList<Object> outObject = new LinkedList<>();
        SocketContext socketContext = new SocketContext(this);
        while (!socket.isClosed() && !socket.isInputShutdown()) {
            try {
                InputStream in = socket.getInputStream();
                int b = in.read();
                byteBuffer.put(b);
                if (in.available() > 0) {
                    int length = in.read(cache);
                    if (length > 0) {
                        byteBuffer.write(cache, 0, length);
                    }
                }
                readHandler(byteBuffer, socketContext);

            } catch (Exception e) {
                if (socket.isClosed()) {
                    break;
                }
                e.printStackTrace();
            }
        }
    }

    @Override
    public void close() throws IOException{
        socket.close();
    }
}
